﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using zTalk.Network;

namespace zTalk
{
    public partial class EditProfile : Window
    {
        OpenFileDialog opf;
        private string tempAvatar64;

        public EditProfile()
        {
            InitializeComponent();

            opf = new OpenFileDialog();
            opf.CheckFileExists = true;
            imgOld.Source = App.DecodeAvatar(App.User.Avatar);

            App.Handler.UpdateProfile += new PacketEventHandler(Handler_UpdateProfile);
            App.Handler.GetProfile += new PacketEventHandler(Handler_GetProfile);
            App.Handler.UpdatePassword += new PacketEventHandler(Handler_UpdatePassword);
            App.Handler.SaveAvatar += new PacketEventHandler(Handler_SaveAvatar); 

            Packet packet = Packet.Create(
                Opcodes.GET_PROFILE, 
                Json.Encode<string[]>(new string[] { App.User.Username })
            );
            App.Client.SendPacket(packet);
        }

        private void btnSave_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                errorPaneSave.Visibility = Visibility.Hidden;
                triggerLoadingSave(true);

                if (txtAbout.Text.Length > 100)
                {
                    throw new Exception("! About you is too long");
                }
                if (txtName.Text.Length > 100)
                {
                    throw new Exception("! Your name is too long");
                }
                if (txtEmail.Text.Length > 100)
                {
                    throw new Exception("! Email is too long");
                }

                int gender = 0;
                if (rbMale.IsChecked == true)
                {
                    gender = 1;
                }
                else if (rbFemale.IsChecked == true)
                {
                    gender = 2;
                }

                string[] data = { 
                    txtAbout.Text, txtName.Text, txtEmail.Text, gender.ToString() 
                };
                Packet packet = Packet.Create(
                    Opcodes.UPDATE_PROFILE,
                    Json.Encode<string[]>(data)
                );
                App.Client.SendPacket(packet);
            }
            catch (Exception exc)
            {
                triggerLoadingSave(false);
                lblErrorsSave.Content = exc.Message;
                errorPaneSave.Visibility = Visibility.Visible;
            }
        }

        void Handler_GetProfile(object sender, PacketEventArgs ea)
        {
            string[] data = (string[])ea.Result;
            Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate {
                txtAbout.Text = data[0];
                txtName.Text = data[1];
                txtEmail.Text = data[2];
                switch (int.Parse(data[3]))
                {
                    case 1:
                        rbMale.IsChecked = true; break;
                    case 2:
                        rbFemale.IsChecked = true; break;
                    case 0:
                    default:
                        rbNone.IsChecked = true; break;
                }
            }));
        }

        void Handler_UpdateProfile(object sender, PacketEventArgs ea)
        {
            triggerLoadingSave(false);

            if ((bool)ea.Result == false)
            {
                Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate {
                    lblErrorsSave.Content = "! Error saving information";
                    errorPaneSave.Visibility = Visibility.Visible;
                }));
            }
            else
            {
                Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate {
                    App.User.About = txtAbout.Text;
                    App.SendUserChange();
                }));
            }
        }

        private void btnChange_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                errorPaneChange.Visibility = Visibility.Hidden;
                triggerLoadingChange(true);

                if (txtNewpass.Password != txtNewpass2.Password)
                {
                    throw new Exception(
                        "! Password and confirm password don't match");
                }
                if (txtNewpass.Password.Length < 3 || 
                    txtNewpass.Password.Length > 20)
                {
                    throw new Exception(
                        "! New password have to be between 3 and 20 characters");
                }

                string[] data = { 
                    App.Sha1(txtOldpass.Password), 
                    App.Sha1(txtNewpass.Password) 
                };
                Packet packet = Packet.Create(
                    Opcodes.UPDATE_PASSWORD,
                    Json.Encode<string[]>(data)
                );
                App.Client.SendPacket(packet);
            }
            catch (Exception exc)
            {
                triggerLoadingChange(false);
                lblErrorsChange.Content = exc.Message;
                errorPaneChange.Visibility = Visibility.Visible;
            }
        }

        void Handler_UpdatePassword(object sender, PacketEventArgs ea)
        {
            triggerLoadingChange(false);

            if ((bool)ea.Result == false)
            {
                Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate {
                    lblErrorsChange.Content = "! Invalid Old Password";
                    errorPaneChange.Visibility = Visibility.Visible;
                }));
            }
        }

        private void btnBrowse_Click(object sender, RoutedEventArgs e)
        {
            opf.FileName = string.Empty;
            if (opf.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                try
                {
                    imgNew.Source = new BitmapImage(new Uri(opf.FileName));
                    btnSet.Content = "Save Avatar";
                }
                catch
                {
                    System.Windows.MessageBox.Show("Invalid image file", 
                        "Error", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                }
            }
        }

        private void btnSet_Click(object sender, RoutedEventArgs e)
        {
            btnSet.Content = "Processing";
            btnSet.IsEnabled = false;

            string avatar64 = string.Empty;
            tempAvatar64 = string.Empty;

            if (opf.FileName != string.Empty)
            {
                Image img = Image.FromFile(opf.FileName);
                Image thumb = img.GetThumbnailImage(40, 40, null, (IntPtr)0);

                MemoryStream stream = new MemoryStream();
                thumb.Save(stream, ImageFormat.Png);

                avatar64 = Convert.ToBase64String(stream.ToArray());
                tempAvatar64 = avatar64;
            }

            Packet packet = Packet.Create(
                Opcodes.SAVE_AVATAR,
                Json.Encode<string[]>(new string[] { avatar64 })
            );
            App.Client.SendPacket(packet);
        }

        void Handler_SaveAvatar(object sender, PacketEventArgs ea)
        {
            Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate {
                btnSet.Content = "Remove Avatar";
                btnSet.IsEnabled = true;
                opf.FileName = string.Empty;

                App.User.Avatar = tempAvatar64;
                imgOld.Source = imgNew.Source;
                imgNew.Source = App.DecodeAvatar(null);

                App.SendUserChange();
            }));
        }

        private void triggerLoadingSave(bool start)
        {
            Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate {
                btnSave.Content = (start == true) ? "Processing" : "Save";
                btnSave.IsEnabled = (start != true);
            }));
        }

        private void triggerLoadingChange(bool start)
        {
            Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate {
                btnChange.Content = (start == true) ? "Processing" : "Change";
                btnChange.IsEnabled = (start != true);
            }));
        }
    }
}
